#ifndef __CTRL_PROTOCOL_H
#define __CTRL_PROTOCOL_H

#include <stdint.h>
#include <stddef.h>

#ifndef __packed
#define __packed
#endif

/*------------------ Ctrl Protocol Packet ----------------------*/
__packed typedef struct {
    uint8_t     pre;        /* preamble - only CTRLPROT_PRE */
    uint8_t     src;        /* source - @enum CtrlProt_Src_e */
    uint8_t     op;         /* opcode - @enum ctrl_prot_op_device_t or @enum ctrl_prot_op_ble_t */
    uint8_t     len;        /* length of data */
    uint32_t    ticks;      /* timestamp */
    uint8_t     data[54];   /* data - @struct ctrl_prot_data_control_t, etc */
    uint16_t    padding;    /* padding for crc16 - Poly 0x8005 (modbus) */
} ctrl_prot_t;
typedef ctrl_prot_t Ctrl_Prot_t;

/*---------------- Ctrl Protocol Section Value -----------------*/

#define CTRLPROT_PRE                ((uint8_t)0xAA)

typedef enum {
    CTRLPROT_SRC_HOST           =   0x5F,
    CTRLPROT_SRC_DEVICE         =   0x55,
    CTRLPROT_SRC_BLE            =   0x5A,
} ctrl_prot_src_t;

typedef enum {
    CTRLPROT_OP_DEVICE_CONTROL  =   0x01,
    CTRLPROT_OP_DEVICE_CONTROLP =   0x02,
} ctrl_prot_op_device_t;

typedef enum {
    CTRLPROT_OP_HOST_POSITION   =   0x02,
    CTRLPROT_OP_HOST_ACK        =   0x10,
} ctrl_prot_op_host_t;

typedef enum {
    CTRLPROT_OP_BLE_CONNECT     =   0xE1,
    CTRLPROT_OP_BLE_DISCONNECT  =   0xE2,
} ctrl_prot_op_ble_t;

/*---------------- Ctrl Protocal Data Structure ----------------*/

// typedef struct {
//     uint16_t group:4;
//     uint16_t btn:12;
// } ctrl_button_t;
typedef uint16_t ctrl_button_t;

__packed typedef struct {
    int8_t left_x;
    int8_t left_y;
    int8_t right_x;
    int8_t right_y;
} ctrl_joystick_t;

__packed typedef struct {
    ctrl_joystick_t    joystick;
    ctrl_button_t      button;
} ctrl_prot_data_control_t;
typedef ctrl_prot_data_control_t CtrlProt_Data_Control_t;

__packed typedef struct {
    float               pos_x;
    float               pos_y;
    float               angle;
} ctrl_prot_data_position_t;

__packed typedef struct {
    uint32_t            tx_ticks;
} ctrl_prot_data_ack_t;

typedef enum 
{
    Button_Mask_X   = 0x0001,
    Button_Mask_Y   = 0x0002,
    Button_Mask_A   = 0x0004,
    Button_Mask_B   = 0x0008,
    Button_Mask_U   = 0x0010,
    Button_Mask_R   = 0x0020,
    Button_Mask_L   = 0x0040,
    Button_Mask_D   = 0x0080,
    Button_Mask_JL  = 0x0100,
    Button_Mask_JR  = 0x0200, 

    Button_Mask_Group = 0xF000,
} button_mask_t;

/*------------------ Tools ------------------------*/
ctrl_prot_t *ctrl_recv_char_to_pack(uint8_t ch);
int ctrl_send_pack_append_crc(ctrl_prot_t *msg);
#define ctrl_button_get_group(btn)      ((btn & Button_Mask_Group) >> 12)
#define ctrl_button_set_group(btn, g)   (btn = (btn & ~Button_Mask_Group) | (g << 12))
#define ctrl_button_no_group(btn)       (btn & ~Button_Mask_Group)
#endif /* !__CTRL_PROTOCOL_H */

